package com.minew.beaconset.db;

import android.content.Context;
import android.database.Cursor;
import android.text.TextUtils;
import android.util.Log;

import com.minew.beaconset.db.bean.DbResult;
import com.minew.beaconset.db.ex.DbException;
import com.minew.beaconset.db.sqlite.DbModelSelector;
import com.minew.beaconset.db.sqlite.Selector;
import com.minew.beaconset.db.sqlite.SqlInfo;
import com.minew.beaconset.db.sqlite.WhereBuilder;
import com.minew.beaconset.db.table.DbModel;
import com.minew.beaconset.db.util.IOUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Create by 游德禄 on 2019-9-9
 * 数据库管理工具
 */
public class DbHelper {
    private static DbManager db ;
    private static String dbName = "data.db";
    /**
     * 初始化数据库并获得DB对象
     * @param mContext
     * @return
     */
    public static DbManager getInstance(Context mContext){
        if (db == null) {
            synchronized (DbHelper.class) {
                if (db == null) {
                    DbManager.DaoConfig config = new DbManager.DaoConfig(mContext);
                    config.setDbName(dbName);
                    config.setDbOpenListener(new DbManager.DbOpenListener() {
                        @Override
                        public void onOpened(DbManager db) {
                            db.getDatabase().enableWriteAheadLogging();
                        }
                    });
                    db = DbManager.create(config);
                    db.configAllowTransaction(true);
                    db.configDebug(false);
                }
            }
        }
        return db;
    }

    /**
     * 获取表名
     * @param cla
     * @return
     */
    public static String getTableName(Class cla){
        String tableName = cla.getName();
        tableName = tableName.replaceAll("\\.","_");
        return tableName;
    }
    /**
     * 初始化
     */
    public static void initData(){

    }


    //创建表
    public static boolean createTable(Class<?> cla){
        try {
            db.createTableIfNotExist(cla);
            return true;
        }catch (DbException e){
        }
        return false;
    }

    /**
     * 通过ID查询单条数据
     * @param cls
     * @param id
     * @param <T>
     * @return
     */
    public static <T>T findById(Class<?> cls, Object id){
        Object entity = null;
        try{
            entity = db.findById(cls,id);
        }catch (DbException e){
            Log.e("["+cls.getName()+"]findById",e.getMessage());
        }
        return (T)entity;
    }


    /**
     * 根据条件 查找单个
     * @param selector
     * @return
     */
    public static <T>T findFirst(Selector selector){
        Object entity = null;
        try{
            entity = db.findFirst(selector);
        }catch (DbException e){
            Log.e("findFirst",e.getMessage());
        }
        return (T)entity;
    }

    /**
     * 保存单条 返回id
     * @param obj
     * @return
     */
    public static <T>T saveBindingId(Object obj){
        Object id =null;
        try{
            boolean saved = db.saveBindingId(obj);
            if(saved){
                return (T)obj;
            }
        }catch (DbException e){
            Log.e("saveBindingId",e.getMessage());
        }
        return null;
    }

    /**
     * 保存单条
     * @param obj
     * @return
     */
    public static boolean save(Object obj){
        try{
            db.save(obj);
        }catch (DbException e){
            Log.e("save",e.getMessage());
            return false;
        }
        return true;
    }
    /**
     * 保存数据,单条或多条
     * @param entity
     * @return
     */
    public static boolean save(List<?> entity){
        if(entity==null||entity.size()==0){
            return false;
        }
        try{
                db.saveAll(entity);
        }catch (DbException e){
            Log.e("save",e.getMessage());
            return false;
        }
        return true;
    }

    /**
     * 保存数据,单条或多条 并返回ID
     * @param entity
     * @return
     */
    public static List<?> saveBindingIdAll(List<?> entity){
        if(entity==null||entity.size()==0){
            return null;
        }
        try{
            db.saveBindingIdAll(entity);
            return entity;
        }catch (DbException e){
            Log.e("saveBindingIdAll",e.getMessage());
        }
        return null;
    }

    /**
     *  全部替换（慎用）
     *  如果不存在就新建，如果存在就全部替换
     *  注意 ：如果没赋值的字段也会被全部替换
     * @param obj
     * @return
     */
    public static boolean replace(Object obj){
        try{
            db.replace(obj);
        }catch (DbException e){
            Log.e("replace",e.getMessage());
            return false;
        }
        return true;
    }

    /**
     * 全部替换 同上
     * @param entities
     * @return
     */
    public static boolean replaceAll(List<?> entities){
        try{
            db.replaceAll(entities);
        }catch (DbException e){
            Log.e("replaceAll",e.getMessage());
            return false;
        }
        return true;
    }

    /**
     * 保存或更新，全部
     * @param entity
     * @return
     */
    public static boolean saveOrUpdate(List<?> entity, String... updateColumnNames){
        if(entity==null||entity.size()==0){
            return false;
        }
        try{
                db.saveOrUpdateAll(entity,updateColumnNames);
        }catch (DbException e){
            Log.e("saveOrUpdate",  "->"+e.getMessage());
            return false;
        }
        return true;
    }



    public interface DbCallback{
        void afterDo(boolean result, Object data);
    }
    /**
     * 保存单条
     * @param obj
     * @return
     */
    public static boolean saveOrUpdate(Object obj, String... updateColumnNames){
        if(obj==null){
            return false;
        }
        try{
            db.saveOrUpdate(obj,updateColumnNames);
        }catch (DbException e){
            Log.e("saveOrUpdate",obj.getClass().toString()+"->"+e.getMessage());
            return false;
        }
        return true;
    }

    /**
     * 更新单条数据
     * @param entity
     * @param whereBuilder
     * @param updateColumnNames
     * @return
     */
    public static boolean update(Object entity, WhereBuilder whereBuilder, String... updateColumnNames){
        if(entity==null){
            return false;
        }
        try {
            db.update(entity,whereBuilder,updateColumnNames);
        }catch (DbException e){
            Log.e("update",e.getMessage());
            return false;
        }
        return true;
    }

    /**
     * 更新单条数据
     * @param entity
     * @param updateColumnNames
     * @return
     */
    public static boolean update(Object entity, String... updateColumnNames){
        if(entity==null){
            return false;
        }
        try {
            db.update(entity,updateColumnNames);
        }catch (DbException e){
            Log.e("update",e.getMessage());
            return false;
        }
        return true;
    }

    /**
     * 更新多条数据
     * @param entity
     * @param updateColumnNames
     * @return
     */
    public static boolean updateAll(List<?> entity, WhereBuilder whereBuilder, String... updateColumnNames){
        if(entity==null){
            return false;
        }
        try {
            db.updateAll(entity,whereBuilder,updateColumnNames);
        }catch (DbException e){
            Log.e("updateAll",e.getMessage());
            return false;
        }
        return true;
    }

    /**
     * 更新多条数据
     * @param entity
     * @param updateColumnNames
     * @return
     */
    public static boolean updateAll(List<?> entity, String... updateColumnNames){
        if(entity==null){
            return false;
        }
        try {
            db.updateAll(entity,updateColumnNames);
        }catch (DbException e){
            Log.e("update",e.getMessage());
            return false;
        }
        return true;
    }

    /**
     * 删除单条
     * @param obj
     * @return
     */
    public static boolean delete(Object obj){
        if(obj==null){
            return false;
        }
        try {
            db.delete(obj);
        }catch (DbException e){
            Log.e("delete",e.getMessage());
            return false;
        }
        return true;
    }

    /**
     * 删除全部
     * @param cla
     * @return
     */
    public static boolean deleteAll(Class<?> cla){
        try {
            db.deleteAll(cla);
        }catch (DbException e){
            Log.e("delete",e.getMessage());
            return false;
        }
        return true;
    }

    /**
     * 通过ID删除
     * @param cla
     * @param id
     * @return
     */
    public static boolean deleteById(Class<?> cla, Object id){
        try {
            db.deleteById(cla,id);
        }catch (DbException e){
            Log.e("deleteById",e.getMessage());
            return false;
        }
        return true;
    }
    /**
     * 删除数据 单条或多条
     * @param entity
     * @return
     */
    public static boolean delete(List<?> entity){
        if(entity.size()==0){
            return false;
        }
        try{
            db.deleteAll(entity);
        }catch (DbException e){
            Log.e("delete",e.getMessage());
            return false;
        }
        return true;
    }

    /**
     * 按条件删除某张表的数据
     * @param cls
     * @param whereBuilder
     * @return
     */
    public static boolean delete(Class<?> cls, WhereBuilder whereBuilder){
        try{
            db.delete(cls,whereBuilder);
        }catch (DbException e){
            Log.e("delete",e.getMessage());
            return false;
        }
        return true;
    }

    /**
     * 查询某张表的数据
     * @param cls
     * @return
     */
    public static long count(Class<?> cls){
        long count = 0l;
        try{
            count = db.count(cls);
        }catch (DbException e){
            Log.e("count",e.getMessage());
        }
        return count;
    }

    /**
     * 根据条件查询数量
     * @param selector
     * @return
     */
    public static long count(Selector selector){
        long count = 0l;
        try{
            count = db.count(selector);
        }catch (DbException e){
            Log.e("count",e.getMessage());
        }
        return count;
    }

    /**
     * 查询某张表的所有数据
     * @param cls
     * @param <T>
     * @return
     */
    public static <T> List<T> findAll(Class<T> cls){
        List<T> list = null;
        try{
            list = db.findAll(cls);
        }catch (DbException e){
            Log.e("findAll",e.getMessage());
        }
        return list;
    }



    /**
     * 根据条件查询某些数据
     * @param selector
     * @param <T>
     * @return
     */
    public static <T> List<T> findAll(Selector selector){
        List<T> list = null;
        try{
            list = db.findAll(selector);
        }catch (DbException e){
            Log.e("findAll",e.getMessage());
        }
        return list;
    }

    /**
     * 判断表是否存在
     * @param cla
     * @return
     */
    public static boolean tableIsExist(Class<?> cla){
        try {
            return db.tableIsExist(cla);
        }catch (DbException e){
            Log.e("tableIsExist",e.getMessage());
        }
        return false;
    }


    /**
     * 通用模型 查询第一条数据
     * @param sql
     * @return
     */
    public static  DbModel findDbModelFirst(String sql){
        try {
            SqlInfo sqlInfo = new SqlInfo();
            sqlInfo.setSql(sql);
            return  db.findDbModelFirst(sqlInfo);
        }catch (DbException e){
            Log.e("findDbModelFirst",e.getMessage());
        }
        return null;
    }

    /**
     *  复杂查询
     * @param selector
     * @return
     */
    public static  DbModel findDbModelFirst(DbModelSelector selector){
        try {
            return  db.findDbModelFirst(selector);
        }catch (DbException e){
            Log.e("findDbModelFirst",e.getMessage());
        }
        return null;
    }

    /**
     *  复杂查询
     * @param selector
     * @return
     */
    public static List<DbModel> findDbModelAll(DbModelSelector selector){
        try {
            return  db.findDbModelAll(selector);
        }catch (DbException e){
            Log.e("findDbModelAll",e.getMessage());
        }
        return null;
    }

    /**
     * 复杂查询
     * @param sql
     * @return
     */
    public static List<DbModel> findDbModelAll(String sql){
        try {
            SqlInfo selector = new SqlInfo();
            selector.setSql(sql);
            return  db.findDbModelAll(selector);
        }catch (DbException e){
            Log.e("findDbModelAll",e.getMessage());
        }
        return null;
    }
    /**
     * 执行查询 sql
     * 返回map结果集
     * 结构
     * 行 - >列  ->列名 对应 值
     * @param selector
     * @return
     */
    public static DbResult exec(Selector selector){
        return exec(selector.toString());
    }

    /**
     *  执行查询 sql
     * 返回map结果集
     * @param sql
     * @return
     */
    public static DbResult exec(String sql){
        DbResult dbResult = new DbResult();
        dbResult.setSuccess(false);
        if(TextUtils.isEmpty(sql)){
            return dbResult;
        }
        List<Map<String, Object>> list = new ArrayList<>();
        Cursor cursor = null;
        try {
            cursor = db.execQuery(sql);
            while (cursor.moveToNext()){
                Map<String, Object> map = new HashMap<>();
               int count =  cursor.getColumnCount();
                for(int i = 0 ; i < count;i++){
                    Object val = null;
                    switch (cursor.getType(i)){
                        case Cursor.FIELD_TYPE_NULL:
                            break;
                        case Cursor.FIELD_TYPE_INTEGER:
                            val = cursor.getInt(i);
                            break;
                        case Cursor.FIELD_TYPE_FLOAT:
                            val = cursor.getFloat(i);
                            break;
                        case Cursor.FIELD_TYPE_STRING:
                            val = cursor.getString(i);
                            break;
                        case Cursor.FIELD_TYPE_BLOB:
                            val = cursor.getBlob(i);
                            break;
                    }
                    map.put(cursor.getColumnName(i),val);
                }
                list.add(map);
            }
            dbResult.setSuccess(true);
            dbResult.setData(list);
        }catch (DbException e){
            dbResult.setSuccess(false);
            dbResult.setMessage(e.getMessage());
        }finally {
            if(cursor!=null){
                IOUtils.closeQuietly(cursor);
            }
        }
        return dbResult;
    }

    /**
     *  获取表的列名
     * @param table
     * @return
     */
    public static List<String> getTableCloumn(Class table){
        List<String> column = new ArrayList<>();
        String sql = "select * from " + getTableName(table);
        Cursor cursor = null;
        try {
            cursor = db.execQuery(sql);
            if (cursor != null) {
                int count = cursor.getColumnCount();
                for (int j = 0; j < count; j++) {
                    column.add(cursor.getColumnName(j));
                }
            }
        }catch (DbException e){
        }finally {
            if(cursor!=null){
                IOUtils.closeQuietly(cursor);
            }
        }
        return column;
    }
    //执行非查询sql
    public static DbResult exec_nonquery(String sql){
        DbResult dbResult = new DbResult();
        dbResult.setSuccess(false);
        if(TextUtils.isEmpty(sql)){
            dbResult.setMessage("sql is empty!");
            return dbResult;
        }
        try {
             db.execNonQuery(sql);
            dbResult.setMessage("success");
            dbResult.setSuccess(true);
            return  dbResult;
        }catch (DbException e){
            dbResult.setMessage(e.getMessage());
            dbResult.setSuccess(false);
            return dbResult;
        }
    }
}
